package com.oraclefmw.crusher;

import java.io.File;
import java.util.Properties;
import java.util.Vector;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

import com.oraclefmw.crusher.core.FileSplitter;
import com.oraclefmw.crusher.core.Fragment;
import com.oraclefmw.crusher.core.WorkerFactory;

public class Main {

	public static final int CHUNK_SIZE_KB = 16 * 1024;
	public static final int PAGE_SIZE = 500;
	
	public static final int THREAD_COUNT = 5;
	
	public static final String SOURCE_DIR = "/Users/gniu/Repository/01.sales/01.saleskit/00.packaging/";
	public static final String DEST_DIR = "/Users/gniu/Workbench/dest/";
	public static final String SUFFIX = ".*";

	private ExecutorService exec;
	private BlockingQueue<Fragment> queue;
	private Properties props;

	public void initialize() {

		exec = Executors.newFixedThreadPool(THREAD_COUNT);
		queue = new LinkedBlockingQueue<Fragment>();
		props = new Properties();

		// for common
		props.setProperty("worker_type", "jms");

		// need for file worker
		props.setProperty("dest_dir", DEST_DIR);

		// need for jms worker
		props.setProperty("page_size", Integer.toString(PAGE_SIZE));
	}

	private void scanFiles(Vector<File> vfiles, File file) {

		if (vfiles == null)
			vfiles = new Vector<File>();

		if (file.isDirectory()) {
			/*File[] files = file.listFiles(new FileFilter() {
				public boolean accept(File pathname) {
					return pathname.isDirectory()
							|| pathname.getPath().endsWith(SUFFIX);
				}
			});*/
			
			File[] files = file.listFiles();
			for (File one : files)
				scanFiles(vfiles, one);
		} else {

			vfiles.add(file);
		}

	}

	private int calPageCount(long total) {
		long fragmentCount = total / CHUNK_SIZE_KB;

		fragmentCount = (CHUNK_SIZE_KB * fragmentCount < total) ? (fragmentCount + 1)
				: fragmentCount;

		long pageCount = fragmentCount / PAGE_SIZE;

		pageCount = (PAGE_SIZE * pageCount < fragmentCount) ? (pageCount + 1)
				: pageCount;
		
		return (int)pageCount;
	}

	public void start() {

		Vector<File> files = new Vector<File>();

		scanFiles(files, new File(SOURCE_DIR));

		long total = 0;

		for (File file : files) {

			total += file.length();
			exec.submit(new FileSplitter(queue, file, CHUNK_SIZE_KB));
		}

		System.out.printf("split file count: %d.\r\n", files.size());

		int workerCount = calPageCount(total);
		
		for (long i = 0; i < workerCount; i++) {

			exec.submit(WorkerFactory.getInstance(queue, props));
		}

		System.out.printf("started %d worker threads.\r\n", workerCount);

		exec.shutdown();
	}

	public static void main(String[] args) throws Exception {

		Main main = new Main();
		main.initialize();
		main.start();
	}
}
